/* Copyright (c) 2011 Jordan Gray, MIT; see COPYRIGHT */


#include "string.h"
#include <iostream>
#include <list>
#include <string>

namespace ch11ex02 {

String::String() { // default to empty string
  p_rep_ = new Srep(0,"");
}

String::String(const String& str) {
  str.p_rep_->num_ref_++;
  p_rep_ = str.p_rep_; // share representation
}

String::~String() {
  if( --p_rep_->num_ref_ == 0) delete p_rep_;
}

String& String::operator=(const String& str) {
  // I think copy constructor(pass by value)+swap data members would be better in every way!
  str.p_rep_->num_ref_++; // protects against "str = str"
  if(--p_rep_->num_ref_ == 0) delete p_rep_;
  p_rep_ = str.p_rep_;
  return *this;
}

String::String(const char * p_str) {
  std::cout << "String::String(const char *)\n";
  p_rep_ = new Srep(strlen(p_str), p_str);
}

String& String::operator=(const char* p_str) {
  if(p_rep_->num_ref_ == 1) {
    p_rep_->assign(strlen(p_str), p_str);
  }
  else {
    p_rep_->num_ref_--;
    p_rep_ = new Srep(strlen(p_str), p_str);
  }
  return *this;
}

std::ostream& operator<<(std::ostream& out, const String& str) {
  out << str.p_rep_->p_buf_;
  return out;
}

std::istream& operator>>(std::istream& in, String& str) {
//  std::string tmp;
//  in >> tmp;
//  str.p_rep_->assign(strlen(tmp.c_str()), tmp.c_str());
//  return in;
  char buf[20];
  int index = 0; char c;
  while (isspace(c = in.get())) {}
  in.putback(c);
  while (!isspace(c = in.get())) {
      buf[index++] = c;
  }
  in.putback(c);
  str.p_rep_->assign(index, buf);
  return in;
}

String& String::operator+=(const String& str) {
  p_rep_ = p_rep_->get_own_copy();
  p_rep_->extend(str.p_rep_->num_char_, str.p_rep_->p_buf_);
  return *this;
}
String& String::operator+=(const char * p_buf) {
  p_rep_ = p_rep_->get_own_copy();
  p_rep_->extend(strlen(p_buf), p_buf);
  return *this;
}
String operator+(const String& str_a, const String& str_b) {
  //return String(str_a) += str_b;
  String::Srep * p_rep = new String::Srep(str_a.p_rep_->num_char_, str_a.p_rep_->p_buf_,
                           str_b.p_rep_->num_char_, str_b.p_rep_->p_buf_ );
  return String(p_rep);
}
String operator+(const String& str_a, const char * p_buf) {
  //return String(str_a) += str_b;
  String::Srep * p_rep = new String::Srep(str_a.p_rep_->num_char_, str_a.p_rep_->p_buf_,
                           strlen(p_buf), p_buf );
  return String(p_rep);
}

/*String& operator+=(const String&);
String& operator+=(const char*);

String operator+(const String&, const String&);
String operator+(const String&, const char*);*/

} // namespace ch11ex02

